/*
 * Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.huawei.cloudphone.virtualdevice.common;

import com.huawei.cloudphone.api.CloudPhoneManager;

import java.nio.ByteBuffer;

public class RingBufferVirtualDeviceIO implements IVirtualDeviceIO{
    private RingBuffer<ByteBuffer> mRingBuffer;
    private int mDataLen;
    private int mDataOffset;
    private byte[] mDataBuffer;
    private Object mObjectLock = new Object();
    private static final int VIRTUAL_CAMERA = 0;
    private static final int VIRTUAL_MICROPHONE = 1;
    private static final int VIRTUAL_SENSOR = 2;

    public RingBufferVirtualDeviceIO() {
        mDataOffset = 0;
        mDataBuffer = null;
        mDataLen = 0;
        mRingBuffer = new RingBuffer<ByteBuffer>();
    }


    @Override
    public int readN(byte[] data, int offset, int length) {
        int ret;
        synchronized (mObjectLock) {
            if (mDataOffset < mDataLen && mDataBuffer != null) {
                int oneTimeReadLength = Math.min(length, mDataLen - mDataOffset);
                System.arraycopy(mDataBuffer, mDataOffset, data, offset, oneTimeReadLength);
                mDataOffset += oneTimeReadLength;
                ret = oneTimeReadLength;
            } else {
                ByteBuffer byteBuffer = (ByteBuffer) mRingBuffer.get();
                if (byteBuffer != null) {
                    mDataBuffer = new byte[byteBuffer.capacity()];
                    byteBuffer.get(mDataBuffer, 0, mDataBuffer.length);
                    mDataOffset = 0;
                    mDataLen = mDataBuffer.length;
                }
                ret = 0;
            }
        }
        return ret;
    }

    @Override
    public int writeN(byte[] data, int offset, int length, int deviceType) {
        synchronized (mObjectLock) {
            CloudPhoneManager.createCloudPhoneInstance().sendVirtualDeviceData((byte) deviceType, data);
        }
        return length;
    }

    public void fillData(byte[] data) {
        ByteBuffer buffer = ByteBuffer.wrap(data);
        mRingBuffer.put(buffer);
    }
}
